// File: KeyRecommander.h
//
// Created by 唐建 on 2023/12/1.
// 关键字查询
//

#ifndef KEYRECOMMANDER_H
#define KEYRECOMMANDER_H

// Macros to disable copying and moving
#define DISALLOW_COPY(cname)                                    \
  cname(const cname &) = delete;                    \
  auto operator=(const cname &)->cname & = delete;

#define DISALLOW_MOVE(cname)                               \
  cname(cname &&) = delete;                    \
  auto operator=(cname &&)->cname & = delete;

#define DISALLOW_COPY_AND_MOVE(cname) \
  DISALLOW_COPY(cname);               \
  DISALLOW_MOVE(cname);

#include "../../src/Reactor/TcpConnection.h"
#include "../json/json.hpp"
#include <pthread.h>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <memory>
class TcpConnection;

using TcpConnectionPtr = std::shared_ptr<TcpConnection>;

//词典
class Dict {
public:
    using DictVector = std::vector<std::pair<std::string, int>>;
    using IndexTable = std::map<std::string, std::set<int>>;
    using WordVectorPtr = std::shared_ptr<std::vector<std::pair<std::string, int>>>;

private:
    static Dict *_pDictZh;
    static Dict *_pDictEn;
    static pthread_once_t _pOnceZh;
    static pthread_once_t _pOnceEn;
    DictVector _dict;
    IndexTable _indexTable;
    int _dictType; // 1 中文字典 2 英文字典

public:
    DISALLOW_COPY_AND_MOVE(Dict);

    static Dict *getInstance(int dictType);

    WordVectorPtr doQuery(const std::string &word);

    DictVector &getIndexTable();

    IndexTable &getDict();

private:
    explicit Dict(int dictType);

    ~Dict() = default;

    static void dictInitZh();
    static void dictInitEn();

    static void destroy();

    void init(const std::string &dictDBPath);
};

struct CandidateResult {
    int _dist; //距离
    int _freq; //频率
    std::string _word; //关键词

    CandidateResult(std::string word, int freq, int dist);

    friend bool operator<(const CandidateResult &lhs, const CandidateResult &rhs)
    {
        if (lhs._dist > rhs._dist) {
            return true;
        }
        if (rhs._dist > lhs._dist)
            return false;
        if (lhs._freq < rhs._freq)
            return true;
        if (rhs._freq < lhs._freq)
            return false;
        return lhs._word < rhs._word;
    }

    friend bool operator>(const CandidateResult &lhs, const CandidateResult &rhs)
    {
        return rhs < lhs;
    }

    friend bool operator<=(const CandidateResult &lhs, const CandidateResult &rhs)
    {
        return !(rhs < lhs);
    }

    friend bool operator>=(const CandidateResult &lhs, const CandidateResult &rhs)
    {
        return !(lhs < rhs);
    }
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CandidateResult, _word, _freq, _dist);

class KeyRecommander {
private:
    using CanResultPriQue = std::priority_queue<CandidateResult>;

    std::string _sought; // 搜索词汇
    bool _zhIN; // 搜索词包含中文
    TcpConnectionPtr _coon; // 客户端连接
    CanResultPriQue _priQue; // 候选搜索结果的优先队列

public:
    // 搜索的关键词 客户端连接
    KeyRecommander(std::string sought, TcpConnectionPtr coon);

    // 执行搜索的入口
    std::string doQuery();

private:
    static bool containZh(std::string &sought);

    std::string returnNoAnswer();
};

#endif //KEYRECOMMANDER_H
